package app.controllers.api;

import app.Const;
import app.base.AuthController;
import app.constant.MemberConstant;
import app.dtos.MemberDto;
import app.jobs.InviteMemberJob;
import app.kit.AuthRedisKit;
import app.kit.CommonKit;
import app.kit.DESCodecKit;
import app.kit.SmsCodeKit;
import app.models.basic.Msgs;
import app.models.member.Account;
import app.models.member.Member;
import app.models.member.MemberLock;
import app.services.auth.AuthInterceptor;
import app.services.auth.AuthParam;
import app.services.bus.BusContext;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.jfinal.aop.Before;
import com.jfinal.ext.interceptor.GET;
import com.jfinal.ext.interceptor.POST;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import goja.StringPool;
import goja.Validator;
import goja.mvc.AjaxMessage;
import goja.mvc.kit.Servlets;
import goja.mvc.render.CaptchaRender;
import goja.plugins.redis.JedisKit;
import goja.security.goja.SecurityKit;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * The url member Controller.
 * </p>
 *
 * @author sagyf yang
 * @version 1.0
 * @since JDK 1.6
 */
public class MemberController extends AuthController {

    /**
     * 会员信息
     * the url /member
     */
    @Before({GET.class, AuthInterceptor.class})
    @AuthParam(auth = true)
    public void index() {

        if(isLogin()){

        } else {

            renderAjaxFailure("请先进行登录！");
            return;
        }

        final String auth_code = getAuthCode();
        final Member member = AuthRedisKit.getMember(auth_code);
        if (member == null) {
        }
        Member show_center = Member.dao.findByIdWithShowCenter(member.getNumber(StringPool.PK_COLUMN).intValue());
        if (show_center != null) {
            renderAjaxSuccess(show_center);
        } else {
            renderJson(AjaxMessage.nodata());
        }
    }


    /**
     * 注册会员接口
     */
    @Before({POST.class, AuthInterceptor.class})
    public void register() {

        String plant_pwd = getPara("plant_pwd");
        String captcha = getPara("captcha");
        String phone = getPara("phone");
        String invite_mobile = getPara("invite_mobile");

        if (Strings.isNullOrEmpty(phone) || Strings.isNullOrEmpty(captcha) || Strings.isNullOrEmpty(plant_pwd)) {
            renderAjaxFailure("参数错误");
            return;
        }

        if (!CommonKit.isMoible(phone)) {
            renderAjaxFailure("请输入正确的手机号码");
            return;
        }
        if (!Strings.isNullOrEmpty(invite_mobile) && !Validator.isMobile(invite_mobile)) {

            renderAjaxFailure("请输入正确的手机号码");
            return;
        }

        if (StringUtils.equals(invite_mobile, phone)) {
            renderAjaxFailure("邀请人手机号码不能与注册号码一致");
            return;
        }


        if (SmsCodeKit.checkRegisted(phone, captcha)) {
            renderAjaxFailure("您输入的验证码不正确");
        } else {
            // 手机号码验证唯一性
            Member phone_member = Member.dao.findbyPhone(phone);
            if (phone_member != null) {
                renderAjaxFailure("手机号码已经被注册，请更换。");
                return;
            }
            MemberDto memberDto = new MemberDto(phone, plant_pwd, invite_mobile, captcha);
            final Member member = memberDto.toModel();
            final Account account = new Account();
            boolean ok = Db.tx(new IAtom() {
                @Override
                public boolean run() throws SQLException {
                    if (member.save()) {
                        account.set(Const.FIELD_MEMBER, member.getNumber(StringPool.PK_COLUMN).intValue());
                        return account.save();
                    }
                    return false;
                }
            });
            if (ok) {
                // 注册成功，需要清除注册码信息
                SmsCodeKit.clearRegisted(memberDto.phone);

                String uuid = getAttrForStr(AuthInterceptor.ATTR_UUID);
                String auth_code = DESCodecKit.encrypt(phone + RandomStringUtils.random(8), uuid);
                final int memberId = member.getNumber(StringPool.PK_COLUMN).intValue();
                AuthRedisKit.login(memberId, member, auth_code);

                // 返回信息中不带这两个
                member.remove(Member.FIELD_SALT);
                member.remove(Member.FIELD_PASSWORD);
                final HashMap<String, Object> result = Maps.newHashMap();
                result.put("auth_code", auth_code);
                result.put(Const.FIELD_MEMBER, member);
                new InviteMemberJob(phone, invite_mobile, memberId, DateTime.now()).now();
                renderAjaxSuccess(result);
            } else {
                renderAjaxFailure("注册失败，请稍后重试");
            }
        }
    }


    /**
     * 会员登录接口
     */
    @Before({POST.class, AuthInterceptor.class})
    public void signin() {

        String phone = getPara("phone");
        if (!CommonKit.isMoible(phone)) {
            renderAjaxFailure("请输入正确的手机号码");
            return;
        }
        String password = getPara(Member.FIELD_PASSWORD);
        if (Strings.isNullOrEmpty(password)) {
            renderAjaxFailure("请输入登录密码");
        }
        String captcha = getPara("captcha");
        final boolean validate = CaptchaRender.validate(this, captcha);
        if (!validate) {
            renderAjaxFailure("请输入正确的验证码");
            return;
        }
        Member member = Member.dao.findbyPhone(phone);
        if (member == null) {
            renderJson(AjaxMessage.NODATA);
        } else {
            final int member_id = member.getNumber(StringPool.PK_COLUMN).intValue();
            boolean login_status = false;
            try {
                if (member.getNumber(Const.FIELD_STATUS).intValue() == MemberConstant.LOCK) {
                    renderAjaxFailure("账户已锁定，无法登录");
                    return;
                }

                final boolean pwd_check = SecurityKit.checkPassword(member.getStr(Member.FIELD_SALT),
                        member.getStr(Member.FIELD_PASSWORD), password);

                if (pwd_check) {

                    final HashMap<String, Object> result = Maps.newHashMap();
                    String auth_code = AuthRedisKit.getAuthCode(member_id);
                    if (Strings.isNullOrEmpty(auth_code)) {
                        String uuid = getAttrForStr(AuthInterceptor.ATTR_UUID);
                        auth_code = DESCodecKit.encrypt(RandomStringUtils.random(4) + phone + RandomStringUtils.random(4), uuid);
                        // 返回信息中不带这两个
                        member.remove("salt");
                        member.remove("password");
                    }
                    AuthRedisKit.login(member_id, member, auth_code);
                    result.put("auth_code", auth_code);
                    result.put(Const.FIELD_MEMBER, member);
                    login_status = true;
                    renderAjaxSuccess(result);
                } else {
                    Integer size = JedisKit.get("failurelogin:" + phone);
                    if (size == null) {
                        size = 1;
                        JedisKit.set("failurelogin:" + phone, size);
                    } else {
                        if (size >= 5) {
                            MemberLock.dao.record(member_id, Servlets.getIp(getRequest()));
                            member.set(Const.FIELD_STATUS, MemberConstant.LOCK);
                            member.update();
                            renderAjaxFailure("输入错误密码次数过多，账户已锁定");
                        }
                        size = size + 1;
                        JedisKit.set("failurelogin:" + phone, size);
                    }


                    renderAjaxFailure("您输入的密码不正确");
                }
            } finally {
                BusContext.postLogin(member_id, member.getStr("phone"), DateTime.now(), Servlets.getIp(getRequest()), login_status);
            }

        }
    }

    /**
     * 退出请求
     */
    @Before({POST.class, AuthInterceptor.class})
    @AuthParam(auth = true)
    public void signout() {

        int memberId = getMemberId();
        AuthRedisKit.logout(getAuthCode(), String.valueOf(memberId));
        renderAjaxSuccess();
    }


    /**
     * 会员消息
     */
    @Before({GET.class, AuthInterceptor.class})
    @AuthParam(auth = true)
    public void message() {

        int page = getParaToInt(0, 1);
        final Member member = getMember();
        List<Msgs> msgs = Msgs.dao.findByMember(member.getNumber(StringPool.PK_COLUMN).intValue(), page);
        renderAjaxSuccess(msgs);
    }

    /**
     * 修改登录密码
     */
    @Before({POST.class, AuthInterceptor.class})
    @AuthParam(auth = true)
    public void password() {
        // 原始密码
        String original_pwd = getPara("original_pwd");
        if (Strings.isNullOrEmpty(original_pwd)) {
            renderAjaxFailure("原始密码不能为空");
            return;
        }
        String new_pwd = getPara(Member.FIELD_PASSWORD);
        if (Strings.isNullOrEmpty(new_pwd)) {
            renderAjaxFailure("请输入新的登录密码");
            return;
        }

        Member member = Member.dao.findById(getMemberId());

        if (!SecurityKit.checkPassword(member.getStr(Member.FIELD_SALT), member.getStr(Member.FIELD_PASSWORD), original_pwd)) {
            renderAjaxFailure("您输入的原始密码不符，无法修改登录密码");
            return;
        }


        // 设置交易密码
        member.generatePassword(new_pwd);
        boolean ok = member.update();
        // 设置交易密码OK

        if (ok) {
            renderAjaxSuccess();
        } else {
            renderAjaxFailure();
        }
    }
}